//




#include <stdio.h>
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_iadc.h"
#include "em_gpio.h"

#include "nb_adc.h"


#include "app/framework/include/af.h"




/*******************************************************************************
*******************************   DEFINES   ***********************************
******************************************************************************/

// Set CLK_ADC to 1000kHz (this corresponds to a sample rate of 10ksps)
#define CLK_SRC_ADC_FREQ        1000000  // CLK_SRC_ADC
#define CLK_ADC_FREQ            10000   // CLK_ADC

// Upper and lower bound for Window Comparator
#define WINDOW_UPPER_BOUND       0xC000
#define WINDOW_LOWER_BOUND      0x4000

// When changing GPIO port/pins above, make sure to change xBUSALLOC macro's
// accordingly.
#define IADC_INPUT_BUS          CDBUSALLOC
#define IADC_INPUT_BUSALLOC     GPIO_CDBUSALLOC_CDEVEN0_ADC0


#define HFRCOEM23_FREQ          cmuHFRCOEM23Freq_1M0Hz

// HFXO frequency set for most common radio configurations
#define HFXO_FREQ               38400000

// CTUNE value for the BRD4181A HFXO oscillator
#define HFXO_CTUNE_VALUE        120

/*******************************************************************************
***************************   GLOBAL VARIABLES   *******************************
******************************************************************************/

/// Stores latest ADC sample
static volatile IADC_Result_t sample;
static volatile double singleResult;



// timer clock enable
static void nb_clock_init(void)
{
	CMU_ClockSelectSet(cmuClock_IADCCLK ,  cmuSelect_HFRCOEM23 );

}


/**************************************************************************//**
* @brief  IADC Initializer
*****************************************************************************/
void nb_adc_single_init (void)
{
  // Declare init structs
  IADC_Init_t init = IADC_INIT_DEFAULT;
  IADC_AllConfigs_t initAllConfigs = IADC_ALLCONFIGS_DEFAULT;
  IADC_InitSingle_t initSingle = IADC_INITSINGLE_DEFAULT;
  IADC_SingleInput_t initSingleInput = IADC_SINGLEINPUT_DEFAULT;

  // Reset IADC to reset configuration in case it has been modified
  IADC_reset(IADC0);

  // Select HFXO as the EM01GRPA clock
 // CMU_ClockSelectSet(cmuClock_EM01GRPACLK, cmuSelect_HFRCOEM23);

  // Configure IADC clock source to use the HFXO (EM01GRPA)
  CMU_ClockSelectSet(cmuClock_IADCCLK, cmuSelect_HFRCOEM23);

  // Modify init structs and initialize
  init.warmup = iadcWarmupKeepWarm;

  // Set the HFSCLK prescale value here
  init.srcClkPrescale = IADC_calcSrcClkPrescale(IADC0, CLK_SRC_ADC_FREQ, 0);

  // Set lower bound for window compare
  //init.greaterThanEqualThres = WINDOW_LOWER_BOUND;

  // Set upper bound for window compare
  //init.lessThanEqualThres = WINDOW_UPPER_BOUND;

  // Configuration 0 is used by both scan and single conversions by default
  // Use unbuffered AVDD as reference
  initAllConfigs.configs[0].reference = iadcCfgReferenceVddx;

  // Divides CLK_SRC_ADC to set the CLK_ADC frequency for desired sample rate
  initAllConfigs.configs[0].adcClkPrescale = IADC_calcAdcClkPrescale(IADC0,
                                                                    CLK_ADC_FREQ,
                                                                    0,
                                                                    iadcCfgModeNormal,
                                                                    init.srcClkPrescale);

  // Divides VDD by 2
  //initAllConfigs.configs[0].analogGain = iadcCfgAnalogGain0P5x;

  initSingle.dataValidLevel = _IADC_SCANFIFOCFG_DVL_VALID1;



  // Set conversions to run continuously
  initSingle.triggerAction = iadcTriggerActionContinuous;//iadcTriggerActionContinuous;

  // Configure Input sources for single ended conversion
  //xx  initSingleInput.posInput = iadcPosInputGnd;//iadcPosInputDvdd;// iadcPosInputPortCPin4;

  initSingleInput.posInput = iadcPosInputPortCPin0;
  initSingleInput.negInput = iadcNegInputGnd;

  // Enable window comparisons on this input
  //initSingleInput.compare = true;

  // Initialize IADC
  IADC_init(IADC0, &init, &initAllConfigs);

  // Initialize Scan
  IADC_initSingle(IADC0, &initSingle, &initSingleInput);

  // Allocate the analog bus for ADC0 inputs
  GPIO->IADC_INPUT_BUS |= IADC_INPUT_BUSALLOC;

  // Enable interrupts on window comparison match
  //IADC_enableInt(IADC0, IADC_IF_SINGLECMP);

  // NEWBIT  added
  IADC_enableInt(IADC0, IADC_IF_SINGLEFIFODVL);

  // Enable ADC interrupts
  NVIC_ClearPendingIRQ(IADC_IRQn);
  NVIC_EnableIRQ(IADC_IRQn);
}


void NB_ADC_Start(void)
{
       // Start scan
         IADC_command(IADC0, iadcCmdStartSingle);
}

/**************************************************************************//**
* @brief  ADC Handler
*****************************************************************************/
void IADC_IRQHandler(void)
{
  //IADC_clearInt(IADC0, IADC_IF_SINGLECMP);
	//IADC_enableInt(IADC0, IADC_IF_SINGLEDONE);

  // Read most recent sample
  //sample = IADC_readSingleResult(IADC0);

	sample = IADC_pullSingleFifoResult(IADC0);

  // Calculate input voltage:
  //  For single-ended the result range is 0 to +Vref, i.e.,
  //  for Vref = AVDD = 3.30V, 12 bits represents 3.30V full scale IADC range.
  singleResult = sample.data * 3.3 / 0xFFF;

  // Toggle WSTK LED0 to signal compare event
  //GPIO_PinOutToggle(gpioPortB, 1);

  IADC_clearInt(IADC0, IADC_IF_SINGLEFIFODVL);
}


void nb_adc_single_result_get( IADC_Result_t* adc )
{
       adc->data = sample.data;
       adc->id = sample.id;
}

void nb_adc_single_result_print(void)
{
	sample = IADC_readSingleResult(IADC0);

	emberAfCorePrintln("Adc Result %d, ID %d",
	                   sample.data,
					   sample.id);
}


// ADC inital & start , the main of those code
// normally, call in emberAfMainInitCallback();
void nb_start_running(void)
{
	//nb_clock_init();

	CMU_ClockEnable(cmuClock_GPIO, true);

	  // Set clock frequency to defined value
	CMU_HFRCOEM23BandSet(HFRCOEM23_FREQ);

	nb_adc_single_init();

	NB_ADC_Start();
}

